GlyphRecolor = LibStub("AceAddon-3.0"):NewAddon("GlyphRecolor", "AceConsole-3.0", "AceHook-3.0", "AceEvent-3.0")

local L = LibStub("AceLocale-3.0"):GetLocale("GlyphRecolor", true)
local Gratuity = LibStub("LibGratuity-3.0")

local _REVERSE_CLASSES = {}

local db
local chg_iconsize

local defaults = {
    profile = {
        showred = true,
		showicon = true,
		showborder = false,
		iconsize = 16,
    },
}

local _CLASS_ICONS = {
	["WARRIOR"] = {0, 0.25, 0, 0.25},
	["MAGE"] = {0.25, 0.49609375, 0, 0.25},
	["ROGUE"] = {0.49609375, 0.7421875, 0, 0.25},
	["DRUID"] = {0.7421875, 0.98828125, 0, 0.25},
	["HUNTER"] = {0, 0.25, 0.25, 0.5},
	["SHAMAN"] = {0.25, 0.49609375, 0.25, 0.5},
	["PRIEST"] = {0.49609375, 0.7421875, 0.25, 0.5},
	["WARLOCK"] = {0.7421875, 0.98828125, 0.25, 0.5},
	["PALADIN"] = {0, 0.25, 0.5, 0.75},
	["DEATHKNIGHT"] = {0.25, 0.49609375, 0.5, 0.75},
}

local function buildOptions()
	-- GUI options table
	local options = {
		type = "group",
		icon = "Interface\\Icons\\Trade_Engraving",
		name = "GlyphRecolor",
		get = function( k ) return db[k.arg] end,
		set = function( k, v ) db[k.arg] = v end,
		args = {
			description = {
				type = "description", order = 0,
				name = L["GlyphRecolor will show class icons on glyphs and color their borders. Also unusable glyphs are colored in red."],
			},
			showborder = {
				name = L["Color glyph border"],
				desc = L["Show glyph borders in class colors."],
				type = "toggle",
				arg = "showborder",
				order = 1, width = "full",
			},
			showred = {
				name = L["Color unusable glyphs"],
				desc = L["Show unusable glyphs in red color."],
				type = "toggle",
				arg = "showred",
				order = 2, width = "full",
			},
			showicon = {
				name = L["Show class icons"],
				desc = L["Show class icons on glyphs."],
				type = "toggle",
				arg = "showicon",
				order = 3, width = "full",
			},
			iconsize = {
				name = L["Icon size"],
				desc = L["Size of class icon (top left corner)."],
				type = "range",
				disabled = function()
					return db.showicon == false
				end,
				min = 8, max = 30, step = 1,
				get = function()
					return db.iconsize
				end,
				set = function(info, value)
					db.iconsize = value
					chg_iconsize = true
				end,
				order = 4, width = "single",
			},
		}
	}
	return options
end

function GlyphRecolor:OnInitialize()
	_REVERSE_CLASSES = {}
	for k, v in pairs(RAID_CLASS_COLORS) do
		_REVERSE_CLASSES[(L[k])] = k
	end
	
	self:RegisterEvent("ADDON_LOADED")
	
	self:HookBlizzBags()
	self:HookGuildBank()
	self:HookCombuctor()
	self:HookBagnon()
	self:HookBaggins()
	--self:HookArkInventory()
	self:HookEngBags()
	
	self.db = LibStub("AceDB-3.0"):New("GlyphRecolorDB", defaults)
    
	db = self.db.profile
	chg_iconsize = false
	
	LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable("GlyphRecolor", buildOptions)
	LibStub("AceConfigDialog-3.0"):AddToBlizOptions("GlyphRecolor", "GlyphRecolor")
	
    self:RegisterChatCommand("glyphrecolor", function() InterfaceOptionsFrame_OpenToCategory(LibStub("AceConfigDialog-3.0").BlizOptions["GlyphRecolor"].frame) end)
    self:RegisterChatCommand("glrec", function() InterfaceOptionsFrame_OpenToCategory(LibStub("AceConfigDialog-3.0").BlizOptions["GlyphRecolor"].frame) end)	
end

function GlyphRecolor:HookBlizzBags()
	self:SecureHook("ContainerFrame_Update")
	self:SecureHook("BankFrameItemButton_Update")
end

function GlyphRecolor:HookGuildBank()
	if not GuildBankFrame_Update or self:IsHooked("GuildBankFrame_Update") then return end
	
	self:SecureHook("GuildBankFrame_Update") 
end

function GlyphRecolor:HookBaggins()
	if Baggins then
		self:SecureHook(Baggins, "UpdateItemButton", "BagginsUpdate")
	end
end

function GlyphRecolor:HookCombuctor()
	if not Combuctor or self:IsHooked(Combuctor.Item, "Update") then return end
	
	self:SecureHook(Combuctor.Item, "Update", "CombuctorUpdate")
end

function GlyphRecolor:HookBagnon()
	if not Bagnon then return end
	self:SecureHook(BagnonItem, "Update", "BagnonUpdate")
end

--[[function GlyphRecolor:HookArkInventory()
	if not ArkInventory then return end
	self:SecureHook(ArkInventory, "Frame_Item_Update_QualityBorder", "ArkInventoryUpdate")
end]]--

function GlyphRecolor:HookEngBags()
	if EngInventory_UpdateButton then
		self:SecureHook("EngInventory_UpdateButton", "EngBagsUpdate")
	end
end

function GlyphRecolor:ADDON_LOADED(eventName, addonName)
	if (addonName == "Blizzard_GuildBankUI") then
		self:HookGuildBank()
	end
	
	if (addonName == "Combuctor") then
		self:HookCombuctor()
	end
end

function GlyphRecolor:GetGlyphData(link)
    local _, _, _, _, _, type, class = GetItemInfo(link)
	
	if type ~= L["Glyph"] or not _REVERSE_CLASSES[class] then
		return false, false, ""
	end
	
	Gratuity:SetHyperlink(link)
    
	local Lines = Gratuity:GetText(2, 10, false, true)
    
    if (Lines) then
        for num, line in pairs(Lines) do
            if (line[1] == MINOR_GLYPH) then
                return class, "minor", _REVERSE_CLASSES[class]
            elseif (line[1] == MAJOR_GLYPH) then
                return class, "major", _REVERSE_CLASSES[class]
            end
        end
    end
	
    return class, "major", _REVERSE_CLASSES[class]
end

function GlyphRecolor:PrepareButton(button, hideBorder, hideIcon)
	hideBorder = hideBorder or false
	hideIcon = hideIcon or true
	
	if button.border and button.border.originalTexture then
		button.border:SetTexture(button.border.originalTexture)
	end
	
	if button.hasBorder and hideBorder and button.border then
		button.border:Hide()
	end
	
	if button.hasClassIcon and hideIcon and button.classicon then
		button.classicon:Hide()
	end
	
	if button.hasRecolor then
		SetItemButtonTextureVertexColor(button, 1.0, 1.0, 1.0)
	end
	
	-- cannot create Frames in combat (thanks Blizzard)
	if InCombatLockdown() then return end
	
	if self.db.profile.showborder and not button.border then
		button.border = button:CreateTexture(nil, "OVERLAY")
		button.border:SetTexture([[Interface\AddOns\CWDGPowerUI\CWDGAuction\GlyphRecolor\UI-Glyph-Border]])
		button.border:SetWidth(67)
		button.border:SetHeight(67)
		button.border:SetPoint("CENTER", button)
		button.border:SetBlendMode('BLEND')
		button.border:Hide()
	end    
	
	if self.db.profile.showicon and not button.classicon then
		button.classicon = button:CreateTexture(nil, "OVERLAY")
		button.classicon:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
		button.classicon:SetWidth(db.iconsize)
		button.classicon:SetHeight(db.iconsize)
		button.classicon:SetPoint("TOPLEFT", button, 3, -3)
		button.classicon:Hide()
	end
end

function GlyphRecolor:ColorButton(button, classFile, glyphtype)
	local color = RAID_CLASS_COLORS[classFile]
	
	if not color then return end
	if not glyphtype then glyphtype = "major" end
	
	if self.db.profile.showicon and button.classicon then
		local class = _CLASS_ICONS[classFile]
		button.classicon:SetTexCoord(class[1], class[2], class[3], class[4])
		if chg_iconsize then
			button.classicon:SetWidth(db.iconsize)
			button.classicon:SetHeight(db.iconsize)
		end
		button.classicon:Show()
		button.hasClassIcon = true
	end
	
	if self.db.profile.showborder and button.border then
		if not button.border.originalTexture then
			-- first time we encounter this button
			button.border.originalTexture = button.border:GetTexture();
		end
		
		if glyphtype == "major" then
			button.border:SetTexture([[Interface\AddOns\GlyphRecolor\UI-Glyph-Border]])
		else
			button.border:SetTexture([[Interface\AddOns\GlyphRecolor\UI-MinorGlyph-Border]])
		end
		
		button.border:SetVertexColor(color.r, color.g, color.b, 0.80)
	    button.border:Show()
		button.hasBorder = true
	end
		
	if self.db.profile.showred and (classFile ~= select(2, UnitClass("player"))) then
		SetItemButtonTextureVertexColor(button, 1.0, 0.0, 0.0)
		button.hasRecolor = true
	end
end

-- Blizzard Bank
function GlyphRecolor:BankFrameItemButton_Update(button)
	if button.isBag then return end
	self:PrepareButton(button, true, true)
	
	if button.hasItem == 1 then
		local item = GetInventoryItemLink("player", button:GetInventorySlot());
		
		if item then
			local class, glyphtype, file = self:GetGlyphData(item)
			if (class and glyphtype) then
				self:ColorButton(button, file, glyphtype)
			end
		end
	end
end

-- Blizzard Bags
function GlyphRecolor:ContainerFrame_Update(frame)
	local name = frame:GetName();
	local id = frame:GetID();
	
	for i=1, frame.size, 1 do
		itemButton = getglobal(name.."Item"..i);
		self:PrepareButton(itemButton, true, true)
		
		if itemButton.hasItem == 1 then 	
			item = GetContainerItemLink(id, itemButton:GetID())

			if item then
				local class, glyphtype, file = self:GetGlyphData(item)
				if (class and glyphtype) then
					self:ColorButton(itemButton, file, glyphtype)
				end
			end
		end
	end
end

-- Blizzard GuildBank
function GlyphRecolor:GuildBankFrame_Update()
	local tabnum = GetCurrentGuildBankTab()
    
    for column = 1, 7 do
        for slot = 1, 14 do
            local button = getglobal("GuildBankColumn" .. column .. "Button" .. slot)
            self:PrepareButton(button, true)
			
			local item = GetGuildBankItemLink(tabnum, button:GetID())
            
            if item then
                local class, glyphtype, file = self:GetGlyphData(item)
                if (class and glyphtype) then
                    self:ColorButton(button, file, glyphtype)
                end
            end
        end
    end
end

-- Combuctor
function GlyphRecolor:CombuctorUpdate(combuctor)
	local link = combuctor.hasItem
	
	self:PrepareButton(combuctor)
	
	if link then
		local class, glyphtype, file = self:GetGlyphData(link)
		
		if (class and glyphtype) then
			self:ColorButton(combuctor, file, glyphtype)
		end
	end
end

-- Bagnon
function GlyphRecolor:BagnonUpdate(bagnon)
	local link = bagnon.hasItem
	
	self:PrepareButton(bagnon)
	
	if link then
		local class, glyphtype, file = self:GetGlyphData(link)
		
		if (class and glyphtype) then
			self:ColorButton(bagnon, file, glyphtype)
		end
	end
end

-- Baggins
function GlyphRecolor:BagginsUpdate(baggins, bagframe, button, bag, slot)
	local link = GetContainerItemLink(bag, slot)
	
	self:PrepareButton(button)
	
	if link then
		local class, glyphtype, file = self:GetGlyphData(link)
		
		if (class and glyphtype) then
			self:ColorButton(button, file, glyphtype)
		end
	end
end

-- ArkInventory
--[[function GlyphRecolor:ArkInventoryUpdate(frame)
	if ArkInventory.ValidFrame( frame, true ) == false then
		return
	end
	local framename = frame:GetName()
	local obj_name = "ArkQualityBorder"
	local obj = getfenv()[framename .. obj_name]
	
	if not obj then return end
	
	self:PrepareButtonExact(obj)
	
	local i = ArkInventory.Frame_Item_GetDB( frame )
	
	if i and i.h then
		local class, glyphtype, file = self:GetGlyphData(i.h)
		
		if (class and glyphtype) then
			self:ColorButtonExact(button, file, glyphtype)
		end
	end
end]]--

function GlyphRecolor:EngBagsUpdate(frame, item)
	if ( frame == nil or item == nil ) then return end
	
	self:PrepareButton(frame, true)
	
	if item["itemlink"] then
		local class, glyphtype, file = self:GetGlyphData(item["itemlink"])
		
		if (class and glyphtype) then
			self:ColorButton(frame, file, glyphtype)
		end
	end
	
	
end
